#encoding:utf-8
'''
Created on 6 avr. 2011

@author: paraita

    Perf: question 1.7.1

'''

import socket
import random
import os
import time
import sys

def serveur_test_upload(port):
    rd,wd = os.pipe()
    pid = os.fork()
    if pid:
        os.close(wd)
        #socket d'envoi: on envoie le resultat au client
        s1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        demandeur = 0
        sortie = False
        while not sortie:
            result =  os.read(rd, 1024)
            resultat = result.split(';')
            if resultat[0] == "addr":
                demandeur = resultat[1]
            else:
                if resultat[0] == "elapsed":
                    s1.sendto("elapsed;" + resultat[1], (demandeur, port+1))
                    sortie = True
        s1.close()
        os.close(rd)
        os.waitpid(pid, os.WNOHANG)
    else:
        os.close(rd)
        '''
            ecouteur sur le reseau: des qu'on recoit le flag debut, on commence a chronometrer
            et quand on recoit le flag fin, on stoppe le chronometre, on envoie l'adresse de l'uploader au fork
            qui s'occupe de préparer la réponse à l'uploadeur, ainsi que le temps que ca a pris
        '''
        s2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s2.bind(("", port))
        sortie = False
        while not sortie:
            data,a = s2.recvfrom(1024)
            if data == "debut":
                start_flag = time.time()
                os.write(wd, "addr;" + a[0])
            else:
                if data == "fin":
                    end_flag = time.time()
                    os.write(wd, "elapsed;" + str(end_flag - start_flag))
                    sortie = True
        s2.close()
        os.close(wd)
        sys.exit()

def client_test_upload(addr,port,limite):
    
    pid = os.fork()
    if pid:
        # socket de lecture: attend la réponse du serveur
        s2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s2.bind(("", port+1))
        sortie = False
        while not sortie:
            data,a = s2.recvfrom(1024)
            dataformated = data.split(';')
            if dataformated[0] == "elapsed":
                sortie = True
                print "temps mis pour uploader " + str(limite) + " octets: " + dataformated[1] + " s"
                print "débit moyen d'upload: " + str((limite/float(dataformated[1]))/100) + " ko/s"
        s2.close()
        os.waitpid(pid, os.WNOHANG)
        
    else:
        #socket d'envoi des données
        s1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        i = 0
        s1.sendto("debut",(addr,port))
        while i < limite:
            s1.sendto(str(int(random.random())*1000000), (addr, port))
            i += 1
        s1.sendto("fin", (addr, port))
        s1.close()
        sys.exit()
    
def serveur_test_download(port):
    rd,wd = os.pipe()
    pid = os.fork()
    if pid:
        os.close(wd)
        #socket d'envoi: on envoie le resultat au client
        s1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        demandeur = 0
        sortie = False
        taille_download = 0
        while not sortie:
            result =  os.read(rd, 1024)
            resultat = result.split(';')
            if resultat[0] == "debut":
                demandeur = resultat[1]
                taille_download = int(resultat[2])
                for i in range(taille_download):
                    #if i%25 == 0:
                    #    print "."
                    #else:
                    #    print ".",
                    s1.sendto(str(int(random.random())*1000000), (demandeur, port))
                s1.sendto("fin;", (demandeur, port))
                sortie = True
        s1.close()
        os.close(rd)
        os.waitpid(pid, os.WNOHANG)
    else:
        os.close(rd)
        '''
            ecouteur sur le reseau: quand un client envoie le flag debut
            on itinialise le transfert depuis le serveur vers ce client
            quand on a finit, on envoie le flag fin pour que le client sache
            qu'il peut calculer le debit
        '''
        s2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s2.bind(("", port+1))
        sortie = False
        while not sortie:
            data,a = s2.recvfrom(1024)
            dataf = data.split(';')
            if dataf[0] == "taille":
                os.write(wd, "debut;" + a[0] + ";" + dataf[1])
                sortie = True
        s2.close()
        os.close(wd)
        sys.exit()

def client_test_download(addr,port,limite):
    
    pid = os.fork()
    if pid:
        # socket de lecture: attend la réponse du serveur
        s2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s2.bind(("", port))
        sortie = False
        start_flag = time.time()
        end_flag = 0
        while not sortie:
            data,a = s2.recvfrom(1024)
            data = data.split(';')
            if data[0] == "fin":
                sortie = True
                end_flag = time.time()
                print "temps mis pour downloader " + str(limite) + " octets: " + str(end_flag-start_flag) + " s"
                print "débit moyen du download: " + str((limite/(end_flag-start_flag))/100) + " ko/s"
        s2.close()
        os.waitpid(pid, os.WNOHANG)
        
    else:
        #socket d'envoi des données
        s1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s1.sendto("taille;" + str(limite),(addr,port+1))
        s1.close()
        sys.exit()

def test_upload(port=8080,taille=400000):
    PORT = port
    pid = os.fork()
    if pid:
        serveur_test_upload(PORT)
        os.waitpid(pid, os.WNOHANG)
    else:
        time.sleep(5)
        client_test_upload("127.0.0.1", PORT, taille)
        sys.exit()

def test_download(port=8086,taille=400000):
    PORT = port
    pid = os.fork()
    if pid:
        serveur_test_download(PORT)
        os.waitpid(pid, os.WNOHANG)
    else:
        time.sleep(5)
        client_test_download("127.0.0.1", PORT, taille)
        sys.exit()

if __name__ == '__main__':
    PORT=8310
    TAILLE=400000
    print "Tests en cours avec " + str(TAILLE) + " octets"
    test_upload(port=PORT,taille=TAILLE)
    test_download(port=PORT+2,taille=TAILLE)